home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / dev / c / libiconv_src.lha / tools / 8bit_tab_to_h.c next >
Encoding:
C/C++ Source or Header  |  2000-11-07  |  16.5 KB  |  535 lines

  1. /*
  2.  * Generates an 8-bit character set table from a .TXT table as found on
  3.  * ftp.unicode.org or from a table containing the 256 Unicode values as
  4.  * hexadecimal integers.
  5.  * Examples:
  6.  *
  7.  *   ./8bit_tab_to_h ISO-8859-1 iso8859_1 < tab8859_1
  8.  *   ./8bit_tab_to_h ISO-8859-2 iso8859_2 < tab8859_2
  9.  *   ./8bit_tab_to_h ISO-8859-3 iso8859_3 < tab8859_3
  10.  *   ./8bit_tab_to_h ISO-8859-4 iso8859_4 < tab8859_4
  11.  *   ./8bit_tab_to_h ISO-8859-5 iso8859_5 < tab8859_5
  12.  *   ./8bit_tab_to_h ISO-8859-6 iso8859_6 < tab8859_6
  13.  *   ./8bit_tab_to_h ISO-8859-7 iso8859_7 < tab8859_7
  14.  *   ./8bit_tab_to_h ISO-8859-8 iso8859_8 < tab8859_8
  15.  *   ./8bit_tab_to_h ISO-8859-9 iso8859_9 < tab8859_9
  16.  *   ./8bit_tab_to_h ISO-8859-10 iso8859_10 < tab8859_10
  17.  *   ./8bit_tab_to_h ISO-8859-14 iso8859_14 < tab8859_14
  18.  *   ./8bit_tab_to_h ISO-8859-15 iso8859_15 < tab8859_15
  19.  *   ./8bit_tab_to_h JISX0201.1976-0 jisx0201 < jis0201
  20.  *   ./8bit_tab_to_h TIS620.2533-1 tis620 < tabtis620
  21.  *   ./8bit_tab_to_h KOI8-R koi8_r < tabkoi8_r
  22.  *   ./8bit_tab_to_h KOI8-U koi8_u < tabkoi8_u
  23.  *   ./8bit_tab_to_h ARMSCII-8 armscii_8 < tabarmscii_8
  24.  *   ./8bit_tab_to_h CP1133 cp1133 < tabibm_cp1133
  25.  *   ./8bit_tab_to_h MULELAO-1 mulelao < tabmulelao_1
  26.  *   ./8bit_tab_to_h VISCII1.1-1 viscii1 < tabviscii
  27.  *   ./8bit_tab_to_h TCVN-5712 tcvn < tabtcvn
  28.  *   ./8bit_tab_to_h GEORGIAN-ACADEMY georgian_ac < tabgeorgian_academy
  29.  *   ./8bit_tab_to_h GEORGIAN-PS georgian_ps < tabgeorgian_ps
  30.  *
  31.  *   ./8bit_tab_to_h ISO-8859-1 iso8859_1 < 8859-1.TXT
  32.  *   ./8bit_tab_to_h ISO-8859-2 iso8859_2 < 8859-2.TXT
  33.  *   ./8bit_tab_to_h ISO-8859-3 iso8859_3 < 8859-3.TXT
  34.  *   ./8bit_tab_to_h ISO-8859-4 iso8859_4 < 8859-4.TXT
  35.  *   ./8bit_tab_to_h ISO-8859-5 iso8859_5 < 8859-5.TXT
  36.  *   ./8bit_tab_to_h ISO-8859-6 iso8859_6 < 8859-6.TXT
  37.  *   ./8bit_tab_to_h ISO-8859-7 iso8859_7 < 8859-7.TXT
  38.  *   ./8bit_tab_to_h ISO-8859-8 iso8859_8 < 8859-8.TXT
  39.  *   ./8bit_tab_to_h ISO-8859-9 iso8859_9 < 8859-9.TXT
  40.  *   ./8bit_tab_to_h ISO-8859-10 iso8859_10 < 8859-10.TXT
  41.  *   ./8bit_tab_to_h ISO-8859-14 iso8859_14 < 8859-14.TXT
  42.  *   ./8bit_tab_to_h ISO-8859-15 iso8859_15 < 8859-15.TXT
  43.  *   ./8bit_tab_to_h JISX0201.1976-0 jisx0201 < JIS0201.TXT
  44.  *   ./8bit_tab_to_h KOI8-R koi8_r < KOI8-R.TXT
  45.  */
  46.  
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <stdbool.h>
  50. #include <string.h>
  51.  
  52. int main (int argc, char *argv[])
  53. {
  54.   const char* charsetname;
  55.   const char* c_charsetname;
  56.   const char* filename;
  57.   const char* directory;
  58.   int charset2uni[0x100];
  59.  
  60.   if (argc != 3 && argc != 4 && argc != 5)
  61.     exit(1);
  62.   charsetname = argv[1];
  63.   c_charsetname = argv[2];
  64.   if (argc > 3) {
  65.     filename = argv[3];
  66.   } else {
  67.     char* s = (char*) malloc(strlen(c_charsetname)+strlen(".h")+1);
  68.     strcpy(s,c_charsetname); strcat(s,".h");
  69.     filename = s;
  70.   }
  71.   directory = (argc > 4 ? argv[4] : "");
  72.  
  73.   fprintf(stderr, "Creating %s%s\n", directory, filename);
  74.  
  75.   {
  76.     int i, c;
  77.     c = getc(stdin);
  78.     ungetc(c,stdin);
  79.     if (c == '#') {
  80.       /* Read a unicode.org style .TXT file. */
  81.       for (i = 0; i < 0x100; i++)
  82.         charset2uni[i] = 0xfffd;
  83.       for (;;) {
  84.         c = getc(stdin);
  85.         if (c == EOF)
  86.           break;
  87.         if (c == '\n' || c == ' ' || c == '\t')
  88.           continue;
  89.         if (c == '#') {
  90.           do { c = getc(stdin); } while (!(c == EOF || c == '\n'));
  91.           continue;
  92.         }
  93.         ungetc(c,stdin);
  94.         if (scanf("0x%x", &i) != 1 || !(i >= 0 && i < 0x100))
  95.           exit(1);
  96.         do { c = getc(stdin); } while (c == ' ' || c == '\t');
  97.         if (c != EOF)
  98.           ungetc(c,stdin);
  99.         if (c == '\n' || c == '#')
  100.           continue;
  101.         if (scanf("0x%x", &charset2uni[i]) != 1)
  102.           exit(1);
  103.       }
  104.     } else {
  105.       /* Read a table of hexadecimal Unicode values. */
  106.       for (i = 0; i < 0x100; i++) {
  107.         if (scanf("%x", &charset2uni[i]) != 1)
  108.           exit(1);
  109.         if (charset2uni[i] < 0 || charset2uni[i] == 0xffff)
  110.           charset2uni[i] = 0xfffd;
  111.       }
  112.       if (scanf("%x", &i) != EOF)
  113.         exit(1);
  114.     }
  115.   }
  116.  
  117.   /* Write the output file. */
  118.   {
  119.     FILE* f;
  120.  
  121.     {
  122.       char* fname = malloc(strlen(directory)+strlen(filename)+1);
  123.       strcpy(fname,directory); strcat(fname,filename);
  124.       f = fopen(fname,"w");
  125.       if (f == NULL)
  126.         exit(1);
  127.     }
  128.  
  129.     fprintf(f, "\n");
  130.     fprintf(f, "/*\n");
  131.     fprintf(f, " * %s\n", charsetname);
  132.     fprintf(f, " */\n");
  133.     fprintf(f, "\n");
  134.  
  135.     {
  136.       int i, i1, i2, i3;
  137.       int line[16];
  138.       int tableno;
  139.       struct { int minline; int maxline; } tables[16];
  140.       bool some_invalid;
  141.       bool final_ret_reached;
  142.  
  143.       for (i1 = 0; i1 < 16; i1++) {
  144.         bool all_invalid = true;
  145.         bool all_identity = true;
  146.         for (i2 = 0; i2 < 16; i2++) {
  147.           i = 16*i1+i2;
  148.           if (charset2uni[i] != 0xfffd)
  149.             all_invalid = false;
  150.           if (charset2uni[i] != i)
  151.             all_identity = false;
  152.         }
  153.         if (all_invalid)
  154.           line[i1] = -2;
  155.         else if (all_identity)
  156.           line[i1] = -1;
  157.         else
  158.           line[i1] = 0;
  159.       }
  160.       tableno = 0;
  161.       for (i1 = 0; i1 < 16; i1++) {
  162.         if (line[i1] >= 0) {
  163.           if (i1 > 0 && tableno > 0 && line[i1-1] == tableno-1) {
  164.             line[i1] = tableno-1;
  165.             tables[tableno-1].maxline = i1;
  166.           } else {
  167.             tableno++;
  168.             line[i1] = tableno-1;
  169.             tables[tableno-1].minline = tables[tableno-1].maxline = i1;
  170.           }
  171.         }
  172.       }
  173.       some_invalid = false;
  174.       for (i = 0; i < 0x100; i++)
  175.         if (charset2uni[i] == 0xfffd)
  176.           some_invalid = true;
  177.       if (tableno > 0) {
  178.         int t;
  179.         for (t = 0; t < tableno; t++) {
  180.           fprintf(f, "static const unsigned short %s_2uni", c_charsetname);
  181.           if (tableno > 1)
  182.             fprintf(f, "_%d", t+1);
  183.           fprintf(f, "[%d] = {\n", 16*(tables[t].maxline-tables[t].minline+1));
  184.           for (i1 = tables[t].minline; i1 <= tables[t].maxline; i1++) {
  185.             fprintf(f, "  /* 0x%02x */\n", 16*i1);
  186.             for (i2 = 0; i2 < 2; i2++) {
  187.               fprintf(f, " ");
  188.               for (i3 = 0; i3 < 8; i3++) {
  189.                 i = 16*i1+8*i2+i3;
  190.                 fprintf(f, " 0x%04x,", charset2uni[i]);
  191.               }
  192.               fprintf(f, "\n");
  193.             }
  194.           }
  195.           fprintf(f, "};\n");
  196.         }
  197.         fprintf(f, "\n");
  198.       }
  199.       final_ret_reached = false;
  200.       fprintf(f, "static int\n%s_mbtowc (conv_t conv, wchar_t *pwc, const unsigned char *s, int n)\n", c_charsetname);
  201.       fprintf(f, "{\n");
  202.       fprintf(f, "  unsigned char c = *s;\n");
  203.       if (some_invalid) {
  204.         for (i1 = 0; i1 < 16;) {
  205.           int t = line[i1];
  206.           const char* indent;
  207.           for (i2 = i1; i2 < 16 && line[i2] == t; i2++);
  208.           indent = (i1 == 0 && i2 == 16 ? "  " : "    ");
  209.           if (i1 == 0) {
  210.             if (i2 == 16) {
  211.             } else {
  212.               fprintf(f, "  if (c < 0x%02x) {\n", 16*i2);
  213.             }
  214.           } else {
  215.             if (i2 == 16) {
  216.               fprintf(f, "  else {\n");
  217.             } else {
  218.               fprintf(f, "  else if (c < 0x%02x) {\n", 16*i2);
  219.             }
  220.           }
  221.           if (t == -2) {
  222.             final_ret_reached = true;
  223.           } else if (t == -1) {
  224.             fprintf(f, "%s*pwc = (wchar_t) c;\n", indent);
  225.             fprintf(f, "%sreturn 1;\n", indent);
  226.           } else {
  227.             fprintf(f, "%s", indent);
  228.             some_invalid = false;
  229.             for (i = 16*i1; i < 16*i2; i++)
  230.               if (charset2uni[i] == 0xfffd)
  231.                 some_invalid = true;
  232.             if (some_invalid)
  233.               fprintf(f, "unsigned short wc = ");
  234.             else
  235.               fprintf(f, "*pwc = (wchar_t) ");
  236.             fprintf(f, "%s_2uni", c_charsetname);
  237.             if (tableno > 1)
  238.               fprintf(f, "_%d", t+1);
  239.             fprintf(f, "[c");
  240.             if (tables[t].minline > 0)
  241.               fprintf(f, "-0x%02x", 16*tables[t].minline);
  242.             fprintf(f, "];\n");
  243.             if (some_invalid) {
  244.               fprintf(f, "%sif (wc != 0xfffd) {\n", indent);
  245.               fprintf(f, "%s  *pwc = (wchar_t) wc;\n", indent);
  246.               fprintf(f, "%s  return 1;\n", indent);
  247.               fprintf(f, "%s}\n", indent);
  248.               final_ret_reached = true;
  249.             } else {
  250.               fprintf(f, "%sreturn 1;\n", indent);
  251.             }
  252.           }
  253.           if (!(i1 == 0 && i2 == 16))
  254.             fprintf(f, "  }\n");
  255.           i1 = i2;
  256.         }
  257.         if (final_ret_reached)
  258.           fprintf(f, "  return RET_ILSEQ;\n");
  259.       } else {
  260.         for (i1 = 0; i1 < 16;) {
  261.           int t = line[i1];
  262.           for (i2 = i1; i2 < 16 && line[i2] == t; i2++);
  263.           if (i1 == 0) {
  264.             if (i2 == 16) {
  265.               fprintf(f, "  ");
  266.             } else {
  267.               fprintf(f, "  if (c < 0x%02x)\n    ", 16*i2);
  268.             }
  269.           } else {
  270.             if (i2 == 16) {
  271.               fprintf(f, "  else\n    ");
  272.             } else {
  273.               fprintf(f, "  else if (c < 0x%02x)\n    ", 16*i2);
  274.             }
  275.           }
  276.           if (t == -1)
  277.             fprintf(f, "*pwc = (wchar_t) c;\n");
  278.           else {
  279.             fprintf(f, "*pwc = (wchar_t) %s_2uni", c_charsetname);
  280.             if (tableno > 1)
  281.               fprintf(f, "_%d", t+1);
  282.             fprintf(f, "[c");
  283.             if (tables[t].minline > 0)
  284.               fprintf(f, "-0x%02x", 16*tables[t].minline);
  285.             fprintf(f, "];\n");
  286.           }
  287.           i1 = i2;
  288.         }
  289.         fprintf(f, "  return 1;\n");
  290.       }
  291.       fprintf(f, "}\n");
  292.  
  293.     }
  294.  
  295.     fprintf(f, "\n");
  296.  
  297.     {
  298.       int uni2charset[0x10000];
  299.       bool pages[0x100];
  300.       int line[0x2000];
  301.       int tableno;
  302.       struct { int minline; int maxline; int usecount; const char* suffix; } tables[0x2000];
  303.       bool need_c;
  304.       bool fix_0000;
  305.       int i, j, p, j1, j2, t;
  306.  
  307.       for (j = 0; j < 0x10000; j++)
  308.         uni2charset[j] = 0;
  309.       for (p = 0; p < 0x100; p++)
  310.         pages[p] = false;
  311.       for (i = 0; i < 0x100; i++) {
  312.         j = charset2uni[i];
  313.         if (j != 0xfffd) {
  314.           uni2charset[j] = i;
  315.           pages[j>>8] = true;
  316.         }
  317.       }
  318.       for (j1 = 0; j1 < 0x2000; j1++) {
  319.         bool all_invalid = true;
  320.         bool all_identity = true;
  321.         for (j2 = 0; j2 < 8; j2++) {
  322.           j = 8*j1+j2;
  323.           if (uni2charset[j] != 0)
  324.             all_invalid = false;
  325.           if (uni2charset[j] != j)
  326.             all_identity = false;
  327.         }
  328.         if (all_invalid)
  329.           line[j1] = -2;
  330.         else if (all_identity)
  331.           line[j1] = -1;
  332.         else
  333.           line[j1] = 0;
  334.       }
  335.       tableno = 0;
  336.       for (j1 = 0; j1 < 0x2000; j1++) {
  337.         if (line[j1] >= 0) {
  338.           if (tableno > 0
  339.               && ((j1 > 0 && line[j1-1] == tableno-1)
  340.                   || ((tables[tableno-1].maxline >> 5) == (j1 >> 5)
  341.                       && j1 - tables[tableno-1].maxline <= 8))) {
  342.             line[j1] = tableno-1;
  343.             tables[tableno-1].maxline = j1;
  344.           } else {
  345.             tableno++;
  346.             line[j1] = tableno-1;
  347.             tables[tableno-1].minline = tables[tableno-1].maxline = j1;
  348.           }
  349.         }
  350.       }
  351.       for (t = 0; t < tableno; t++) {
  352.         tables[t].usecount = 0;
  353.         j1 = 8*tables[t].minline;
  354.         j2 = 8*(tables[t].maxline+1);
  355.         for (j = j1; j < j2; j++)
  356.           if (uni2charset[j] != 0)
  357.             tables[t].usecount++;
  358.       }
  359.       for (t = 0, p = -1, i = 0; t < tableno; t++) {
  360.         if (tables[t].usecount > 1) {
  361.           char* s;
  362.           if (p == tables[t].minline >> 5) {
  363.             s = (char*) malloc(5+1);
  364.             sprintf(s, "%02x_%d", p, ++i);
  365.           } else {
  366.             p = tables[t].minline >> 5;
  367.             s = (char*) malloc(2+1);
  368.             sprintf(s, "%02x", p);
  369.           }
  370.           tables[t].suffix = s;
  371.         } else
  372.           tables[t].suffix = NULL;
  373.       }
  374.       {
  375.         p = -1;
  376.         for (t = 0; t < tableno; t++)
  377.           if (tables[t].usecount > 1) {
  378.             p = 0;
  379.             fprintf(f, "static const unsigned char %s_page%s[%d] = {\n", c_charsetname, tables[t].suffix, 8*(tables[t].maxline-tables[t].minline+1));
  380.             for (j1 = tables[t].minline; j1 <= tables[t].maxline; j1++) {
  381.               if ((j1 % 0x20) == 0 && j1 > tables[t].minline)
  382.                 fprintf(f, "  /* 0x%04x */\n", 8*j1);
  383.               fprintf(f, " ");
  384.               for (j2 = 0; j2 < 8; j2++) {
  385.                 j = 8*j1+j2;
  386.                 fprintf(f, " 0x%02x,", uni2charset[j]);
  387.               }
  388.               fprintf(f, " /* 0x%02x-0x%02x */\n", 8*(j1 % 0x20), 8*(j1 % 0x20)+7);
  389.             }
  390.             fprintf(f, "};\n");
  391.           }
  392.         if (p >= 0)
  393.           fprintf(f, "\n");
  394.       }
  395.       need_c = false;
  396.       for (j1 = 0; j1 < 0x2000;) {
  397.         t = line[j1];
  398.         for (j2 = j1; j2 < 0x2000 && line[j2] == t; j2++);
  399.         if (t >= 0)
  400.           j2 = tables[t].maxline+1;
  401.         if (!(t == -2 || (t == -1 && j1 == 0)))
  402.           need_c = true;
  403.         j1 = j2;
  404.       }
  405.       fix_0000 = false;
  406.       fprintf(f, "static int\n%s_wctomb (conv_t conv, unsigned char *r, wchar_t wc, int n)\n", c_charsetname);
  407.       fprintf(f, "{\n");
  408.       if (need_c)
  409.         fprintf(f, "  unsigned char c = 0;\n");
  410.       for (j1 = 0; j1 < 0x2000;) {
  411.         t = line[j1];
  412.         for (j2 = j1; j2 < 0x2000 && line[j2] == t; j2++);
  413.         if (t >= 0) {
  414.           if (j1 != tables[t].minline) abort();
  415.           if (j2 > tables[t].maxline+1) abort();
  416.           j2 = tables[t].maxline+1;
  417.         }
  418.         if (t == -2) {
  419.         } else {
  420.           if (j1 == 0)
  421.             fprintf(f, "  ");
  422.           else
  423.             fprintf(f, "  else ");
  424.           if (t >= 0 && tables[t].usecount == 0) abort();
  425.           if (t >= 0 && tables[t].usecount == 1) {
  426.             if (j2 != j1+1) abort();
  427.             for (j = 8*j1; j < 8*j2; j++)
  428.               if (uni2charset[j] != 0) {
  429.                 fprintf(f, "if (wc == 0x%04x)\n    c = 0x%02x;\n", j, uni2charset[j]);
  430.                 break;
  431.               }
  432.           } else {
  433.             if (j1 == 0) {
  434.               fprintf(f, "if (wc < 0x%04x)", 8*j2);
  435.             } else {
  436.               fprintf(f, "if (wc >= 0x%04x && wc < 0x%04x)", 8*j1, 8*j2);
  437.             }
  438.             if (t == -1) {
  439.               if (j1 == 0)
  440.                 /* If wc == 0, the function must return 1, not -1. */
  441.                 fprintf(f, " {\n    *r = wc;\n    return 1;\n  }\n");
  442.               else
  443.                 fprintf(f, "\n    c = wc;\n");
  444.             } else {
  445.               fprintf(f, "\n    c = %s_page%s[wc", c_charsetname, tables[t].suffix);
  446.               if (tables[t].minline > 0)
  447.                 fprintf(f, "-0x%04x", 8*j1);
  448.               fprintf(f, "];\n");
  449.               if (j1 == 0 && uni2charset[0] == 0)
  450.                 /* If wc == 0, the function must return 1, not -1. */
  451.                 fix_0000 = true;
  452.             }
  453.           }
  454.         }
  455.         j1 = j2;
  456.       }
  457.       if (need_c) {
  458.         if (fix_0000)
  459.           fprintf(f, "  if (c != 0 || wc == 0) {\n");
  460.         else
  461.           fprintf(f, "  if (c != 0) {\n");
  462.         fprintf(f, "    *r = c;\n");
  463.         fprintf(f, "    return 1;\n");
  464.         fprintf(f, "  }\n");
  465.       }
  466.       fprintf(f, "  return RET_ILSEQ;\n");
  467.       fprintf(f, "}\n");
  468.  
  469.     }
  470.  
  471.     if (ferror(f) || fclose(f))
  472.       exit(1);
  473.   }
  474.  
  475. #if 0
  476.  
  477.     int i1, i2, i3, i1_min, i1_max, j1, j2;
  478.  
  479.   i1_min = 16;
  480.   i1_max = -1;
  481.   for (i1 = 0; i1 < 16; i1++)
  482.     for (i2 = 0; i2 < 16; i2++)
  483.       if (charset2uni[16*i1+i2] != 0xfffd) {
  484.         if (i1_min > i1) i1_min = i1;
  485.         if (i1_max < i1) i1_max = i1;
  486.       }
  487.   printf("static const unsigned short %s_2uni[%d] = {\n",
  488.          name, 16*(i1_max-i1_min+1));
  489.   for (i1 = i1_min; i1 <= i1_max; i1++) {
  490.     printf("  /""* 0x%02x *""/\n", 16*i1);
  491.     for (i2 = 0; i2 < 2; i2++) {
  492.       printf("  ");
  493.       for (i3 = 0; i3 < 8; i3++) {
  494.         if (i3 > 0) printf(" ");
  495.         printf("0x%04x,", charset2uni[16*i1+8*i2+i3]);
  496.       }
  497.       printf("\n");
  498.     }
  499.   }
  500.   printf("};\n");
  501.   printf("\n");
  502.  
  503.   for (p = 0; p < 0x100; p++)
  504.     pages[p] = 0;
  505.   for (i = 0; i < 0x100; i++)
  506.     if (charset2uni[i] != 0xfffd)
  507.       pages[charset2uni[i]>>8] = 1;
  508.   for (p = 0; p < 0x100; p++)
  509.     if (pages[p]) {
  510.       int j1_min = 32;
  511.       int j1_max = -1;
  512.       for (j1 = 0; j1 < 32; j1++)
  513.         for (j2 = 0; j2 < 8; j2++)
  514.           if (uni2charset[256*p+8*j1+j2] != 0) {
  515.             if (j1_min > j1) j1_min = j1;
  516.             if (j1_max < j1) j1_max = j1;
  517.           }
  518.       printf("static const unsigned char %s_page%02x[%d] = {\n",
  519.              name, p, 8*(j1_max-j1_min+1));
  520.       for (j1 = j1_min; j1 <= j1_max; j1++) {
  521.         printf("  ");
  522.         for (j2 = 0; j2 < 8; j2++)
  523.           printf("0x%02x, ", uni2charset[256*p+8*j1+j2]);
  524.         printf("/""* 0x%02x-0x%02x *""/\n", 8*j1, 8*j1+7);
  525.       }
  526.       printf("};\n");
  527.     }
  528.   printf("\n");
  529.  
  530. }
  531. #endif
  532.  
  533.   exit(0);
  534. }
  535.